import os.path
import sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))

import click
from operator import itemgetter

from dp_analysis.analysis.base import DrawBase
from dp_analysis.db.connection import Mysql
from dp_analysis.utils.data_search import search_region
from dp_analysis.utils.decorate import decorate


class DrawGeo(DrawBase):
    """
    绘制餐厅的地理坐标图
    """
    def __init__(self):
        super().__init__()

        self.select_dict = {
            "1": self.use_comment,
            "2": self.use_cuisine
        }
        self.save_dict = {
            "1": "geo/评论/",
            "2": "geo/菜系/"
        }
        self.cuisine_count = 20

    @decorate(obj_name="DrawGeo")
    def analyse(self, db, region, select, cuisine_count):
        self.cuisine_count = cuisine_count
        with Mysql("dp", db) as mysql:
            connection = mysql.engine.connect()

            region_list = list()
            if region == "all":
                for (reg,) in connection.execute("SELECT region FROM regional_table_of_delicacies;").fetchall():
                    region_list.append(reg)
            else:
                region_list = [region]

            for region in region_list:
                print(f"正在处理{region}地区...")
                self.search_data(connection, region, select)

    def search_data(self, connection, region, select):
        attr, values, result_dict, category_dict = list(), list(), dict(), dict()
        # self.select_dict.get(select) 通过 select 选择要使用的函数
        for shop_name, value, lng, lat in self.select_dict.get(select)(connection, region, category_dict):
            # 数据记录
            attr.append(shop_name)
            try:
                values.append(int(value or 0))
            except Exception as e:
                values.append(0)
            result_dict.setdefault(shop_name, [lng, lat])

        if select == "1":
            # 如果为 1 ， 则表明使用评论数量来画图（评论数量用来控制每个点的颜色）
            self.draw_map(region, attr, values, map_type=f"{region}", visual_range=[0, 2000],
                          geo_cities_coords=result_dict, save_path=self.save_dict.get(select),
                          visual_text_color="#000")
        else:
            _list = list(set(values))
            pieces = list()
            # 对category_dict中的元素通过值进行排序
            category_list = sorted(category_dict.items(), key=itemgetter(1), reverse=True)
            # 设置每个菜系所具有的属性，进行绘图
            for (category, number) in category_list:
                pieces.append({"min": number, "max": number, "label": category})
            self.draw_map(region, attr, values, map_type=f"{region}", visual_range=[min(_list), max(_list)],
                          geo_cities_coords=result_dict, save_path=self.save_dict.get(select),
                          is_piecewise=True, visual_split_number=len(_list), visual_range_text=['', ''],
                          pieces=pieces)

    @staticmethod
    def use_comment(connection, region, _):
        print("数据读取并处理中...")
        number = 0
        for shop_name, comment_number, lng, \
            lat in connection.execute(f"SELECT shop_name, comment_number, lng, lat "
                                      f"FROM shop_info WHERE region={region!r};").fetchall():
            yield shop_name, comment_number, lng, lat
            number += 1
            if number % 1000 == 0:
                print(f"数据读取并处理{number}条...")
        print(f"数据读取并处理{number}条完成！")

    def use_cuisine(self, connection, region, category_dict):
        print("数据读取并处理中...")
        number, category_set = 0, set()
        for shop_name, category, lng, lat in connection.execute(f'SELECT detailed_address, category, lng, lat '
                                                                f'FROM shop_info WHERE region={region!r} '
                                                                f'AND category NOT IN '
                                                                f'("热门", "评论", "口味", "环境", "服务");').fetchall():
            if len(category_set) > self.cuisine_count and category not in category_set:
                continue
            if category not in category_set:
                category_set.add(category)
            # 记录当前菜系添加后共有多少数量，用来控制绘图时每个菜系的颜色不同
            category_dict.setdefault(category, len(category_set))
            yield shop_name, len(category_set), lng, lat
            number += 1
            if number % 1000 == 0:
                print(f"数据读取并处理{number}条...")
        print(f"数据读取并处理{number}条完成！")

    __call__ = analyse


@click.command()
@click.option("--db", default=0, help="请选择使用的数据库")
@click.option("--region", default="all", help="12大地区通过helpers.py获取")
@click.option("--select", prompt="地理坐标系展示设置[1 or 2]", help="展示设置：评论数量：1； 菜系：2")
@click.option("-c", "--cuisine_count", default=20, help="请选择使用的菜系数量；当select=2时生效")
def main(db, region, select, cuisine_count):
    if region != "all" and region not in search_region(db):
        raise Exception(f"输入地区{region}不在可选范围内...")

    draw = DrawGeo()
    draw.analyse(int(db), region, select, cuisine_count)


if __name__ == '__main__':
    main()
